grant_handle_t shmem_handle;
grant_ref_t shmem_ref;
+ struct page *pagerange;
} tpmif_t;
void tpmif_disconnect_complete(tpmif_t * tpmif);
static tpmif_t *alloc_tpmif(domid_t domid, long int instance)
{
- struct page *page;
tpmif_t *tpmif;
tpmif = kmem_cache_alloc(tpmif_cachep, GFP_KERNEL);
tpmif->tpm_instance = instance;
atomic_set(&tpmif->refcnt, 1);
- page = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE);
- BUG_ON(page == NULL);
- tpmif->mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+ tpmif->pagerange = balloon_alloc_empty_page_range(TPMIF_TX_RING_SIZE);
+ BUG_ON(tpmif->pagerange == NULL);
+ tpmif->mmap_vstart = (unsigned long)pfn_to_kaddr(
+ page_to_pfn(tpmif->pagerange));
list_add(&tpmif->tpmif_list, &tpmif_list);
num_frontends++;
{
num_frontends--;
list_del(&tpmif->tpmif_list);
+ balloon_dealloc_empty_page_range(tpmif->pagerange, TPMIF_TX_RING_SIZE);
kmem_cache_free(tpmif_cachep, tpmif);
}
.cmd = EVTCHNOP_bind_interdomain,
.u.bind_interdomain.remote_dom = tpmif->domid,
.u.bind_interdomain.remote_port = evtchn,
- };
+ };
- if (tpmif->irq) {
- return 0;
- }
+ if (tpmif->irq) {
+ return 0;
+ }
if ((tpmif->tx_area = alloc_vm_area(PAGE_SIZE)) == NULL)
return -ENOMEM;
struct gnttab_map_grant_ref map_op;
struct gnttab_unmap_grant_ref unmap_op;
tpmif_tx_request_t *tx;
+ unsigned long pfn, mfn, mfn_orig;
tx = &tpmif->tx->ring[i].req;
DPRINTK(" Grant table operation failure !\n");
return 0;
}
- set_phys_to_machine(__pa(MMAP_VADDR(tpmif, i)) >> PAGE_SHIFT,
- FOREIGN_FRAME(map_op.
- dev_bus_addr >> PAGE_SHIFT));
+
+ pfn = __pa(MMAP_VADDR(tpmif, i)) >> PAGE_SHIFT;
+ mfn = FOREIGN_FRAME(map_op.dev_bus_addr >> PAGE_SHIFT);
+ mfn_orig = phys_to_machine_mapping[pfn];
+
+ set_phys_to_machine(pfn, mfn);
tocopy = MIN(size - offset, PAGE_SIZE);
}
tx->size = tocopy;
+ set_phys_to_machine(pfn, mfn_orig);
+
gnttab_set_unmap_op(&unmap_op, MMAP_VADDR(tpmif, i),
GNTMAP_host_map, handle);
{
struct backend_info *be = dev->data;
+ if (!be) return 0;
+
if (be->backend_watch.node) {
unregister_xenbus_watch(&be->backend_watch);
kfree(be->backend_watch.node);
return;
}
- if (be->is_instance_set != 0 && be->instance != instance) {
- printk(KERN_WARNING
- "tpmback: changing instance (from %ld to %ld) "
- "not allowed.\n",
- be->instance, instance);
- return;
- }
-
if (be->is_instance_set == 0) {
- be->tpmif = tpmif_find(dev->otherend_id,
- instance);
- if (IS_ERR(be->tpmif)) {
- err = PTR_ERR(be->tpmif);
- be->tpmif = NULL;
- xenbus_dev_fatal(dev,err,"creating block interface");
- return;
- }
be->instance = instance;
be->is_instance_set = 1;
-
- /*
- * There's an unfortunate problem:
- * Sometimes after a suspend/resume the
- * state switch to XenbusStateInitialised happens
- * *before* I get to this point here. Since then
- * the connect_ring() must have failed (be->tpmif is
- * still NULL), I just call it here again indirectly.
- */
- if (be->frontend_state == XenbusStateInitialised) {
- frontend_changed(dev, be->frontend_state);
- }
}
}
*/
tpmif_vtpm_close(be->instance);
device_unregister(&be->dev->dev);
+ tpmback_remove(dev);
break;
case XenbusStateUnknown:
dev->otherend);
return err;
}
+
+ if (!be->tpmif) {
+ be->tpmif = tpmif_find(dev->otherend_id,
+ be->instance);
+ if (IS_ERR(be->tpmif)) {
+ err = PTR_ERR(be->tpmif);
+ be->tpmif = NULL;
+ xenbus_dev_fatal(dev,err,"creating vtpm interface");
+ return err;
+ }
+ }
+
if (be->tpmif != NULL) {
err = tpmif_map(be->tpmif, ring_ref, evtchn);
if (err) {